import React,{Component} from 'react';
import TodoItem from './TodoItem'
import Test from './Test'
import axios from 'axios'


class TodoList extends Component{

  constructor(props){
    super(props);
//当组件的state或者props发生改变时，render函数就会重新执行,
//react重新渲染的效率是非常高的，因为他引入了虚拟DOM（本质上就是js对象）
//js生成dom要比生成js对象要耗损性能的多
//虚拟dom  ['div',{id:'abc'},['span',{},'hello world']]
//dom  <div id="abc"><span>hello world</span></div>
//state数据
// jsx模板
// 数据+模板生成虚拟Dom(本质上是js对象用它来描述虚拟Dom)
// 用虚拟Dom生成真实Dom来显示
// state变化
// 数据+模板生成新的虚拟Dom
// 比较原来的和新的虚拟Dom的区别（使用diff算法：同层比较）
//直接操作Dom，改变Dom里面的内容
    this.state = {
      inputValue:"",
      list:[]
    }
    //组件初始化时,就把this指向确定好,只执行一次，对性能比较好
    this.handleInputChange = this.handleInputChange.bind(this)
    this.handleCllick = this.handleCllick.bind(this)
    this.handleItemDelete = this.handleItemDelete.bind(this)
  }

  componentWillMount() {
    //在渲染前调用,在客户端也在服务端。
    //在组件即将被挂载到页面时调用
    console.log('componentWillMount')
  }
  componentDidMount() { //组件被挂载到页面之后调用
    console.log('componentDidMount')
    //这里写ajax                                                         
    axios.get('api/todolist.json').then((res)=>{
      console.log(res.data)
      this.setState(()=>{
        return{
          list:[...res.data]
        }
      })
    }).catch(function(error){
        console.log(error)
    })
  }


//test初始化时已经传值了，为''，而item必须点击btn才能穿第一个值
  componentWillReceiveProps(newProps) {
  	//在组件接收到一个新的 prop (更新后)时被调用。第一次传参不执行，更新才执行
    console.log('componentWillReceiveProps')
  }

  //组件被更新之前执行  可以清空console运行看打印
  shouldComponentUpdate(newProps, newState) {
      console.log("shouldComponentUpdate")
      return true;
      //你的组件需要被更新吗 返回true后componentWillUpdate才会执行，否不执行
  }
  componentWillUpdate(nextProps, nextState) {
  	//在组件接收到新的props或者state但还没有render时被调用。
        console.log('componentWillUpdate');
        //console.log(nextState);
  }
  componentDidUpdate(prevProps, prevState) {
  	//在组件完成更新后立即调用。
    console.log('componentDidUpdate')
  }

  componentWillUnmount() {
  	//在组件从 DOM 中移除之前立刻被调用。
    console.log('componentWillUnmount')
  }


  handleInputChange(e){
    // this.setState({inputValue:e.target.value})
    //新版语法接受一个函数
    //会报错，setState如果写函数，会变成异步的，为了提升性能
    //所以e需要外面做个保存

    //以下两种可以过去dom
    // const value = e.target.value   
    const value = this.input.value  

    this.setState(() => ({
      //异步的,假设连续调用3次state变更3次数据，
      //时间间隔小时，react把3次setState可以合并成一个
      //只做一次虚拟dom的比对，然后去更新Dom
        inputValue:value   
    }))

  }

  handleCllick(){
      // this.setState({
      //   list:[...this.state.list,this.state.inputValue],
      //   inputValue:''
      // })
      //setState会接受一个参数，是修改前的值，在这里就是this.state
      this.setState((prevState) => ({//异步的
        list:[...prevState.list,prevState.inputValue],
        inputValue:''  
      }))
  }

  handleItemDelete(index){
    // const list = [...this.state.list];
    // list.splice(index,1)
    // this.setState({list:list})
    //Es6 语法list:list可直接写成list
    this.setState((prevState) => {
      const list = [...prevState.list];
      list.splice(index,1)
      return {list}
    })

  }

  render(){
    console.log('TodoList render 执行')
    return (
      <React.Fragment>
          <div >                      
              <input  
                type="text"  className="inpt"
                placeholder="请输入..."
                value={this.state.inputValue}             
                onChange={this.handleInputChange}
                ref = {(e)=>{this.input = e}}
              />
              {/* this.input指向的是e,e对应的是input标签对应的dom元素 */}
              <button onClick={this.handleCllick} >提交</button>         
          </div>
          {/*<ul>
              this.state.list.map((item,index)=>{
                  return (  <TodoItem key={index} 
                                    content={item} 
                                    index={index}
                                    DeleteItem={this.handleItemDelete}
                            />
                         )                                 
              })
              </ul>
            */}
          <ul>
            {this.getTodoItem()}
          </ul>
          <Test content={this.state.inputValue} />
      </React.Fragment>    
    );
  } 

  getTodoItem(){
    return this.state.list.map((item,index)=>{
              return (  <TodoItem key={index} 
                                content={item} 
                                index={index}
                                DeleteItem={this.handleItemDelete}
                        />
                    )                                 
            })   
  }


}


export default TodoList;
